Skip to content

core: nemotron's checkpoint identity moves to core, and GLM's ranks compare the checkpoint by it - #900

Closed
Bizuayeu wants to merge 1 commit into
ashhart:mainfrom
Bizuayeu:pr/glm-checkpoint-contents
Closed

Bizuayeu wants to merge 1 commit into
ashhart:mainfrom
Bizuayeu:pr/glm-checkpoint-contents

Conversation

@Bizuayeu

@Bizuayeu Bizuayeu commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

The third follow-up promised on #804 (comment),
as one commit on main: 781595e4. Since 1.0.12 Nemotron's ranks already agree on a checkpoint's identity before any
weight loads (0089ac9c), so GLM now uses that instead of a second hash of its own.

What this changes

GLM's ranks compared the checkpoint by its folder's last name, which refused identical copies kept under other names.
Nemotron's cuda_identity.zig moves unchanged to core/checkpoint_identity.zig (Nemotron's three callers and the
nemotron.identity export only change their import), and GLM's fingerprint carries its identity(): config.json,
the index, and each shard's name, size and header in name order, the tensors' bytes unread. A hub snapshot's revision
(the folder under snapshots/) is still compared, but only when both ranks read a hub snapshot. The fingerprint's
layout goes to 6.

GLM does not take Content, the every-byte digest Nemotron's ranks compare at ready: GLM's ranks agree once, before
the weights load, and that digest would need a second agreement after it.

Receipt

  • Environment: main at 46a08c18 (TensorFold 1.0.12) plus this change and the split start's probe (glm: a split start checks that every pair of ranks can exchange, before the weights load #899) on one
    branch; three DGX Spark (GB10, sm_121, CUDA 13.3) over RoCE; nvidia/GLM-5.3-Flash-NVFP4 at revision 423acf37.
  • Exactness: the check runs once at start, before the weights load. At TP=3 and TP=2 the concurrent and shared checks
    pass, and at TP=2 four of the server's replies, compared by hash, rounds and accepted drafts, equal main's.
  • Decode speed before and after: n/a, the check runs once at start.
  • Prompt speed before and after: n/a, the check runs once at start.
  • Tests run: on one host zig build test-cuda-host 853 passed (852 at main), zig build test 621 passed and 7
    skipped, with one new test beside the moved ones (the identity unchanged by a dense byte in another folder, and
    changed by another tensor name), zig fmt --check clean, glm-ref and the thin and synthetic lanes checks; at TP=3
    the concurrent (41 PASS) and shared checks, at TP=2 the concurrent, shared and cover checks; 0 failed. lean_check:
    516, as main.
  • Not run, and why: ranks reading copies under different folder names at TP=2 or more (our ranks read the same hub
    snapshot; the host tests cover the identity); Nemotron on GPUs (only its import changes, and its host tests ran).

Checklist

  • Every token still goes through the lane rounds. No serial path, and nothing that needs drafts off.
  • Drafted output equals "draft": false, a resumed prompt equals a fresh one, and concurrent equals solo (the lanes checks above).
  • No precision traded for speed. If the bits change, the description says which sums change and why (no sum changes).
  • Prompt processing is no slower than the last release (the check runs once at start).
  • The description says which platforms I ran, Metal M1 to M5 and CUDA, and which I could not (CUDA on GB10; the family is CUDA's).
  • New tests fail before the change, pass after it, and skip cleanly without their dependency (the fingerprint test's copy under another folder's name, which main's folder-name field refuses; the identity test pins what the moved code already did).
  • Comments and docstrings are one line. No measurements or history in the source.
  • No personal data, machine names, internal hosts or local paths. No AI attribution lines.

…re the checkpoint by it, and a hub snapshot's revision only against another
@Bizuayeu
Bizuayeu force-pushed the pr/glm-checkpoint-contents branch from bce5c60 to 781595e Compare October 16, 2026 12:56
@Bizuayeu Bizuayeu changed the title glm: ranks compare the checkpoint by its contents, not its folder's name core: nemotron's checkpoint identity moves to core, and GLM's ranks compare the checkpoint by it Oct 16, 2026
@Bizuayeu
Bizuayeu marked this pull request as ready for review October 16, 2026 13:24
@Bizuayeu

Copy link
Copy Markdown
Contributor Author

Rebased onto main as 781595e4, and reworked: since 1.0.12, Nemotron's identity() agrees on a checkpoint before any weight loads, which this PR's own hash duplicated. It moves unchanged to core/checkpoint_identity.zig, Nemotron only changes its import, and GLM's fingerprint uses it (layout 6). Title, description and receipt are updated. Ready for review.

@ashhart ashhart mentioned this pull request Oct 17, 2026
@ashhart

ashhart commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Thanks @Bizuayeu for reusing the released checkpoint identity instead of adding another hash. That is the right common owner for Nemotron and GLM startup agreement.

We have prepared the per-file content-digest cache and GLM integration so unchanged shards need not be streamed repeatedly for hashing. Changed files and corrupt cache records force revalidation; metadata or equal headers alone are not checkpoint identity. The host controls cover those cases. Final cross-rank startup, changed-checkpoint refusal and load-time measurements still need their device receipts. Your transport checks remain attached to their exact tested head.

Posted by Ash's AI Assistant Synthena

@Bizuayeu

Copy link
Copy Markdown
Contributor Author

Thank you. One detail for the per-file digest cache. Both passes here take their file list from the index's weight map: the identity before loading, and the digest of every byte. So a shard in a subfolder counts like any other.

NVIDIA's FP4-Local checkpoints depend on that (#1015):

  • GLM-5.3-Flash-FP4-Local keeps one shard in tensors/ (tensors/native-QB.safetensors, 753 MB).
  • Qwen3.8-Flash-Next-FP4-Local keeps all of its shards there.

Those checkpoints stay covered if the cache takes its files from the same weight-map list, rather than from a listing of *.safetensors at the top level. The admission estimate missed exactly those files, since weightBytes counted only the top level. Its fix is on #1015's list.

ashhart added a commit that referenced this pull request Oct 18, 2026
…d per-file digest cache, for every family

Nemotron's checkpoint identity moves to core/checkpoint_identity.zig, as #900 proposed, and its whole-file and
sorted non-expert digests now come from one digest-cache entry a file: the first full read computes both, and a warm
start of the same shards, whole or split across ranks, reads neither again. Split manifests and Hugging Face blob
names are still checked at every finish. The Nemotron engine, its workers, Super VL and the CLI read the shared
module; the fixtures, including a snapshot's blob-name check, move with it to checkpoint_identity_test.zig.

Co-authored-by: Bizuayeu <30091157+Bizuayeu@users.noreply.github.com>
ashhart added a commit that referenced this pull request Oct 18, 2026
…igest cache, so a warm start reads no shard

The ranks' fingerprint carried a SHA-256 that cuda_artifact streamed over the index and every shard at each start, in
one thread: 164 GB, about six minutes for GLM-5.3-Flash EXL3 on a GB10, every time. Each rank now sends the shared
checkpoint identity (core/checkpoint_identity.zig: the metadata, then every shard byte read once in eight threads
and kept per file in the digest cache), so a second start of unchanged shards reads none of them to compare; the
fingerprint's layout is 9. A test writes three one-tensor checkpoints in folders of the same name: different tensor
bytes under identical headers disagree, and a copy agrees. The comparison and its mismatch report follow #900's.

Co-authored-by: Bizuayeu <30091157+Bizuayeu@users.noreply.github.com>
@ashhart

ashhart commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Thank you, @Bizuayeu, for moving checkpoint identity into the common core and exposing the rank-fingerprint gap.

TensorFold 1.1.0 carries shared identity in 20bca34 and the GLM content comparison in 80d99ce, with your co-author credit, on the digest cache from 018e73c. Digests are reused only while the file's recorded identity is unchanged; corrupt or foreign indexes are ignored. Different tensor bytes under identical headers still disagree. Warm starts reuse unchanged shard digests while the ranks compare complete checkpoint content before loading.

The final EXL3 GB10 pair passes 17/17 drafted/plain and 12/12 cached/cache-off chat checks. Those serving results do not replace the separate fingerprint-mismatch validation below.

Host mismatch fixtures passed; two GB10s reused 83/83 shard digests on restart; a deliberately mismatched live pair is not recorded.

Posted by Ash's AI Assistant Synthena

@Bizuayeu

Bizuayeu commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor Author

Host mismatch fixtures passed; two GB10s reused 83/83 shard digests on restart; a deliberately mismatched live pair is not recorded.

(#900 (comment))

A deliberately mismatched live pair on 1.1.0 (76aafcf2): two GB10s over a direct ConnectX-7 link, GLM-5.3-Flash NVFP4 (33 shards), one tensorfold-native binary on both ranks (sha256 b6202d919b376d47), serve per rank with TF_GLM_RANK, TF_GLM_WORLD and NCCL_COMM_ID, and TF_GLM_LAYERS=4 on both (the whole checkpoint also loads on these two GB10s on 1.1.0: #1040). Rank 0 served the pinned Hugging Face snapshot. Rank 1 served a folder of symlinks to that snapshot's files, except its smallest shard, model-00012-of-00033.safetensors (5,915,083,008 bytes), which was a plain copy outside blobs/.

Rank 1's copy of that shard Rank 0 Rank 1
Unchanged (control) served served; checkpoint digest: 5.5 GiB read in 4.5 s, 32/33 cached files
Last byte flipped, 0x42 to 0x43 (header and size unchanged) REFUSE rank settings: rank 1's checkpoint differs from rank 0's (checkpoint metadata or shard bytes), then tensorfold: the ranks' settings differ (each rank's log names the one): start them alike; exit 1 the same REFUSE line, then rank 1: rank 0 stopped (RankMismatch); this rank stops too; exit 1

Both ranks ended about 10 s after starting, before loading any weights. The first start on a cold cache read 190.4 GiB in 288.6 s (rank 0) and 295.8 s (rank 1), 0/33 cached; every later start in the same containers read 0.0 GiB, 33/33 cached.

@ashhart

ashhart commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Shipped in 1.1.0 as 20bca3403 and 80d99ceb9, with digest reuse from 018e73c6c; thanks @Bizuayeu. We're closing it as landed.

Posted by Ash's AI Assistant Synthena

@ashhart ashhart closed this Oct 18, 2026
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…d per-file digest cache, for every family

Nemotron's checkpoint identity moves to core/checkpoint_identity.zig, as ashhart#900 proposed, and its whole-file and
sorted non-expert digests now come from one digest-cache entry a file: the first full read computes both, and a warm
start of the same shards, whole or split across ranks, reads neither again. Split manifests and Hugging Face blob
names are still checked at every finish. The Nemotron engine, its workers, Super VL and the CLI read the shared
module; the fixtures, including a snapshot's blob-name check, move with it to checkpoint_identity_test.zig.

Co-authored-by: Bizuayeu <30091157+Bizuayeu@users.noreply.github.com>
BlivionIaG pushed a commit to BlivionIaG/TensorFold that referenced this pull request Oct 20, 2026
…igest cache, so a warm start reads no shard

The ranks' fingerprint carried a SHA-256 that cuda_artifact streamed over the index and every shard at each start, in
one thread: 164 GB, about six minutes for GLM-5.3-Flash EXL3 on a GB10, every time. Each rank now sends the shared
checkpoint identity (core/checkpoint_identity.zig: the metadata, then every shard byte read once in eight threads
and kept per file in the digest cache), so a second start of unchanged shards reads none of them to compare; the
fingerprint's layout is 9. A test writes three one-tensor checkpoints in folders of the same name: different tensor
bytes under identical headers disagree, and a copy agrees. The comparison and its mismatch report follow ashhart#900's.

Co-authored-by: Bizuayeu <30091157+Bizuayeu@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants